`define VERSION 32'h00000012
//`define NEEDSPI 1
module debugger (
    input           clk,
    input           clk_50M,
    input           reset_n,
    
    //external
    output reg      ch341a_ack,//debug模块请求置1，cs0拉低置0
    output          ch341a_miso,//data out
    input           ch341a_mosi,
    input           ch341a_sck,
    input           ch341a_cs2,//data out
    input           ch341a_cs1,//data in
    input           ch341a_cs0,//cmd in /data out

    //cpu
    output reg          debug_reset_n,
    output reg          halt_debug,
    output reg          debug_step,
    input               halt_cpu,
    //input        [31:0] curr_data,
    //input        [31:0] pcResult,
    //input        [31:0] private_offset,
    //input        [31:0] private_offset_rear,
    input        [31:0] pc,
    input        [31:0] cpu_address,
    input               irq_enable,
    //input        [31:0] irq_addr,

    output              debug_rw,
    output reg   [2:0]  debug_rw_cmd,
    output reg          debug_read_ins,
    output              debug_ins_hold_value,
    output      [31:0]  debug_address_data,
    output reg  [31:0]  debug_address_ins,
    output      [31:0]  debug_writedata_data,

    input       [31:0]  avm_m0_address,
    input               avm_m0_request,
    input               avm_m0_rw,
    input       [31:0]  avm_m0_readdata,
    input               avm_m0_waitrequest,
    input               avm_m1_read,
    input       [31:0]  avm_m1_readdata,
    input               avm_m1_waitrequest,
    input               irq_req,
    input         [4:0] irq_id,

    output       [5:0]  debug_regAddr,
    input       [31:0]  debug_regData,

    output        [7:0] pc_record_index_read,
    input        [35:0] pc_record_data,
    input        [31:0] pc_record_index,
    
    output        [7:0] debug_stash_index_read,
    input        [31:0] debug_stash_data,
    input         [7:0] debug_stash_index,

    //spirom
    output reg        spirom_debug_read_req     ,
    input             spirom_debug_read_ack     ,
    input       [7:0] spirom_debug_read_data    ,
    output reg        spirom_debug_write_req    ,
    input             spirom_debug_write_ack    ,
    output reg  [7:0] spirom_debug_write_data   ,
    output reg        spirom_debug_cs           ,

    //vga
    output reg        vga_control_by_debugger,
    output reg        vga_debugger_read_line_req,
    output reg  [1:0] vga_debugger_read_line_part,
    output      [9:0] vga_debugger_read_line_burst,
    input             vga_debugger_read_line_ack,
    output reg [15:0] vga_debugger_read_line_addr,
    
    output      [9:0] vga_debugger_read_pixel_addr,
    output            vga_debugger_read_pixel_clk,
    input      [15:0] vga_debugger_read_pixel_data,

    output reg [31:0] debug_hid,
    output reg        debug_hid_req,

    //misc
    output reg        debug_flg,
    input      [31:0] debug_tx_to_pc,
    input             debug_tx_to_pc_valid,
    output reg        debug_tx_to_pc_read,
    output reg [31:0] debug_rx_from_pc,
    output reg        debug_rx_from_pc_valid,
    input             debug_rx_from_pc_read,
    output reg [31:0] debug_vga_base_addr,
    input      [31:0] memSize,
    input      [15:0] vga_base_addr,
    output reg        cpu_clk_sel,


    output reg debug_commandFifo,
    output reg [31:0] debug_commandFifoAddr,
    input [31:0] debug_command_read_cur,
    input [31:0] debug_command_write_cur,
    input [31:0] debug_max_command_length,
    input [35:0] debug_q_command,

    input dummy
);
  assign vga_debugger_read_line_burst = 512;

  reg  [31:0]  debug_address;
  assign debug_address_data = debug_address;
  reg  [31:0]  debug_writedata;
  assign debug_writedata_data = debug_writedata;

  assign pc_record_index_read = debug_address[7:0];
  assign debug_stash_index_read = debug_address[7:0];

  reg [23:0] accessTime;
  reg        accessTimeCnt;
  reg        accessTimeCntLast;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      accessTime <= 0;
      accessTimeCnt <= 0;
      accessTimeCntLast <= 0;
    end else begin
      accessTimeCntLast <= accessTimeCnt;
      if(avm_m0_request || avm_m1_read)begin
        accessTimeCnt <= 1;
      end else begin
        accessTimeCnt <= 0;
      end
      if(accessTimeCnt)begin
        if(!accessTimeCntLast)begin
          accessTime <= 0;
        end else begin
          accessTime <= accessTime + 1'b1;
        end
      end
    end
  end
  
  reg command_req;
  reg command_ack;
  reg debug_data_send;
  reg [31:0] debug_data_out;
  wire [31:0] data;
  wire [7:0] command;
  assign debug_regAddr = debug_address[5:0];
  reg transfer_regWriteEna_reg;

  
  
  
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  reg [39:0] ch341a_cmd_data;
  assign data = ch341a_cmd_data[39:8];
  reg ch341a_miso0;

  //https://www.intel.cn/content/www/cn/zh/programmable/products/processors/support.html

  reg [13:0] ch341a_cs2_index;//9+5 512*32 bit , 10+4 1024*16 bit 2048*8 bit
  reg [7:0] ch341a_cs1_addr;
  reg [4:0] ch341a_cs1_index;

  wire [31:0]  transfer_Data;
  
  reg fast;
  
  wire ch341a_miso2 = vga_control_by_debugger ? (
  fast ? 
  vga_debugger_read_pixel_data[10:10] 
  :
  vga_debugger_read_pixel_data[ch341a_cs2_index[3:0]]
  ): transfer_Data[ch341a_cs2_index[4:0]];

  assign ch341a_miso = !ch341a_cs0 ? ch341a_miso0 : ch341a_miso2;

  //增加一个起始地址寄存器
  //ch341a_cs2 作为单读
  //222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

wire BUFGMUX_inst_out;
BUFGMUX BUFGMUX_inst (
  .O(BUFGMUX_inst_out),   // 1-bit output: Clock output
  .I0(clk_50M), // 1-bit input: Clock input (S=0)
  .I1(ch341a_sck), // 1-bit input: Clock input (S=1)
  .S(( (!ch341a_cs2) || (!ch341a_cs1) ))    // 1-bit input: Clock select
);

  wire        transfer_clk = BUFGMUX_inst_out;
//  wire        transfer_clk = (
//                          ( (!ch341a_cs2) || (!ch341a_cs1) )
//                          ? ch341a_sck : clk_50M
//                         );

  wire  [8:0] transfer_Addr_write = (
                          (!ch341a_cs1)?
                            ch341a_cs1_addr :
                            debug_address[10:2]
                         );

  wire  [8:0] transfer_Addr_read = (
                          (!ch341a_cs2) ? 
                            ch341a_cs2_index[12:5] : 
                            debug_address[10:2]
                         );

//uart优化
//debugch341优化 transfer
//用乘法器代替移位逻辑，高32位就是移入的结果


  assign vga_debugger_read_pixel_addr = vga_control_by_debugger ? (fast ? ch341a_cs2_index : ch341a_cs2_index[13:4]) : debug_address[31:1];//transfer_highAddr

`ifdef isXC6SLX16
BUFGMUX BUFGMUX_inst2 (
  .O(vga_debugger_read_pixel_clk),   // 1-bit output: Clock output
  .I0(clk_50M), // 1-bit input: Clock input (S=0)
  .I1(ch341a_sck), // 1-bit input: Clock input (S=1)
  .S(vga_control_by_debugger)    // 1-bit input: Clock select
);
`else
  assign vga_debugger_read_pixel_clk = vga_control_by_debugger ? ch341a_sck : clk_50M;
`endif 

  //ch341a_cs2 作为单读到PC
  always @(negedge ch341a_sck or posedge ch341a_cs2) begin
    if(ch341a_cs2)begin
      ch341a_cs2_index <= 0;
    end else begin
      ch341a_cs2_index <= ch341a_cs2_index + 1'b1;
    end
  end

  wire transfer_WriteEna_cs1 = ch341a_cs1_index==5'b11111;
  wire transfer_WriteEna = (!ch341a_cs1) ? transfer_WriteEna_cs1 : transfer_regWriteEna_reg;
  wire [31:0] transfer_WriteData = (!ch341a_cs1) ? {ch341a_mosi, transfer_temp_data} : debug_writedata; 

  
  
  transferBuff transferBuff_ins(
  .clk(transfer_clk),
  .addr_w(transfer_Addr_write),
  .addr_r(transfer_Addr_read),
  .in(transfer_WriteData),
  .we(transfer_WriteEna),
  .out(transfer_Data)
  );

  
  
  
  //1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
  //ch341a_cs1 作为单写从PC
  reg [30:0] transfer_temp_data;
  always @(negedge ch341a_sck or posedge ch341a_cs1) begin
    if(ch341a_cs1)begin
      ch341a_cs1_index <= 0;
      ch341a_cs1_addr <= 0;
    end else begin
      ch341a_cs1_index <= ch341a_cs1_index + 1'b1;
      if(ch341a_cs1_index==5'b11111)begin
        ch341a_cs1_addr <= ch341a_cs1_addr + 1'b1;
      end
      transfer_temp_data <= {ch341a_mosi, transfer_temp_data[30:1]};
    end
  end



  //00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  //输出，32bit，ack 上升时锁存
  reg [31:0] ch341a_data_out_buff;//out data
  always @(posedge ch341a_sck or posedge ch341a_ack) begin
    if (ch341a_ack) begin//ack拉高时锁存
      ch341a_miso0 <= 0;
      ch341a_data_out_buff <= debug_data_out;
    end else begin
      if(!ch341a_cs0) begin
        ch341a_miso0 <= ch341a_data_out_buff[0];
        ch341a_data_out_buff[30:0] <= ch341a_data_out_buff[31:1];
      end
    end
  end

  always @(posedge clk_50M or negedge reset_n) begin
    if(!reset_n) begin
      ch341a_ack <= 1'b0;
    end else begin
      if(debug_data_send)begin
        ch341a_ack <= 1'b1;
      end 
      if (!ch341a_cs0)begin
        ch341a_ack <= 1'b0;
      end
    end
  end
  
  //5个字节指令加数据
  assign command = ch341a_cmd_data[7:0];
  always @(posedge ch341a_sck) begin
    if(!ch341a_cs0)begin
      ch341a_cmd_data <= {ch341a_mosi, ch341a_cmd_data[39:1]};
    end
  end

  reg ch341a_cs0_buff;//新
  reg ch341a_cs0_buff2;//旧
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      ch341a_cs0_buff <= 1;
      ch341a_cs0_buff2 <= 1;
      command_req <= 0;
    end else begin
      ch341a_cs0_buff <= ch341a_cs0;
      ch341a_cs0_buff2 <= ch341a_cs0_buff;
      
      if(!ch341a_cs0_buff2 && ch341a_cs0_buff)begin //上升沿触发debug指令
        command_req <= 1;
      end
      
      if(command_ack)begin
        command_req <= 0;
      end
    end
  end

  
  
  
  
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  assign debug_ins_hold_value = 0;
  reg mem_read_req;
  reg mem_write_req;
  reg ins_read_req;
  //mem_read
  reg mem_read_req_buff;
  reg mem_read_ack;
  reg [1:0] mem_read_status;
  reg debug_read;
  reg [31:0] avm_m0_readdata_latch;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      mem_read_ack <= 0;
      mem_read_status <= 0;
      debug_read <= 0;
      mem_read_req_buff <= 0;
    end else begin
      mem_read_req_buff <= mem_read_req;

      case(mem_read_status)
      0: begin
        if(mem_read_req_buff && !mem_read_ack)begin
          mem_read_status <= 1;
          debug_read <= 1;
        end
      end
      1: begin
        debug_read <= 0;
        mem_read_status <= 2;
      end
      2: begin
        if(!avm_m0_waitrequest)begin
          avm_m0_readdata_latch <= avm_m0_readdata;
          mem_read_status <= 0;
          mem_read_ack <= 1;
        end
      end

      endcase
      
      if(!mem_read_req_buff && mem_read_ack)begin
        mem_read_ack <= 0;
      end
      
    end
  end

  //mem_write
  reg mem_write_req_buff;
  reg mem_write_ack;
  reg [1:0] mem_write_status;
  reg debug_write;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      mem_write_ack <= 0;
      mem_write_status <= 0;
      debug_write <= 0;
      mem_write_req_buff <= 0;
    end else begin
      mem_write_req_buff <= mem_write_req;

      case(mem_write_status)
      0: begin
        if(mem_write_req_buff && !mem_write_ack)begin
          mem_write_status <= 1;
          debug_write <= 1;
        end
      end
      1: begin
        debug_write <= 0;
        mem_write_status <= 2;
      end
      2: begin
        if(!avm_m0_waitrequest)begin
          mem_write_status <= 0;
          mem_write_ack <= 1;
        end
      end
      endcase
      
      if(!mem_write_req_buff && mem_write_ack)begin
        mem_write_ack <= 0;
      end
    end
  end
  assign debug_rw = debug_read | debug_write;

  
  //ins_read
  reg ins_read_req_buff;
  reg ins_read_ack;
  reg ins_read_status;
  reg [31:0] avm_m1_readdata_latch;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      ins_read_ack <= 0;
      ins_read_status <= 0;
      debug_read_ins <= 0;
      ins_read_req_buff <= 0;
      debug_address_ins <= 0;
    end else begin
      ins_read_req_buff <= ins_read_req;

      case(ins_read_status)
        0: begin
          if(ins_read_req_buff && !ins_read_ack)begin
            ins_read_status <= 1;
            debug_read_ins <= 1;
            debug_address_ins <= debug_address;
          end
        end
        1: begin
          if(!avm_m1_waitrequest)begin
            avm_m1_readdata_latch <= avm_m1_readdata;
            debug_read_ins <= 0;
            ins_read_status <= 0;
            ins_read_ack <= 1;
          end
        end
      endcase
      
      if(!ins_read_req_buff && ins_read_ack)begin
        ins_read_ack <= 0;
      end
      
    end
  end

always @(*)begin
  case(command[6:0])
    8'h02: begin debug_data_out<=123; end
        
    8'h09: begin debug_data_out<=debug_command_read_cur; end
    8'h0A: begin debug_data_out<=debug_command_write_cur; end
    8'h0B: begin debug_data_out<=debug_q_command[31:0]; end
    8'h0C: begin debug_data_out<=debug_q_command[35:32]; end
    8'h0D: begin debug_data_out<=debug_max_command_length; end


    8'h20: begin debug_data_out<=32'h12345678; end //GET_CONST_ECHO
    8'h21: begin debug_data_out<=pc_record_data[35:32]; end //GET_PC_RECORD_DATA_EXT
    8'h22: begin debug_data_out<=accessTime; end //GET_ACCESS_TIME
    8'h23: begin debug_data_out<=avm_m0_address; end //GET_AVM_M0_ADDRESS
    8'h24: begin debug_data_out<=`VERSION; end //GET_CONST_ECHO
    8'h25: begin debug_data_out<=pc_record_data[31:0]; end //GET_PC_RECORD_DATA
    8'h26: begin debug_data_out<=pc_record_index; end //GET_PC_RECORD_INDEX
    8'h27: begin debug_data_out<={avm_m1_waitrequest,halt_cpu,halt_debug,avm_m0_waitrequest,irq_enable,irq_req}; end //GET_MISC
    8'h28: begin debug_data_out<=irq_id; end //GET_IRQ_ID
    8'h29: begin debug_data_out<=cpu_address; end //GET_CPU_ADDRESS
    8'h2A: begin debug_data_out<=pc; end // GET_PC
    8'h2B: begin debug_data_out<=memSize; end // GET_MEM_SIZE
    8'h2C: begin debug_data_out<=vga_base_addr; end // GET_VGA_BASE_ADDR
    8'h2E: begin debug_data_out<=debug_stash_data; end //  GET_DEBUG_STASH_DATA
    8'h2F: begin debug_data_out<=debug_stash_index; end // GET_DEBUG_STASH_INDEX

    //mem read
    8'h30: begin debug_data_out <= avm_m0_readdata_latch; end

    //mem_write
    8'h31: begin debug_data_out<=123; end
    
    //ins read
    8'h32: begin debug_data_out <= avm_m1_readdata_latch; end

    //内存批量 len = data, start = debug_address
    8'h34: begin debug_data_out<=123; end

    8'h35: begin debug_data_out<=123; end

    //reg read
    8'h37: begin debug_data_out <= debug_regData; end
    
    //trans read
    8'h38 : begin debug_data_out <= transfer_Data; end
    
    //trans write
    8'h39 : begin debug_data_out<=123; end

//`ifdef USESPIROM_DEBUG
    8'h72 : begin debug_data_out<=spirom_debug_read_data; end
    8'h73 : begin debug_data_out<=123; end
    8'h74 : begin debug_data_out<=123; end
    
    //spirom 批量
            //内存批量 len = data start = debug_address
    8'h76 : begin debug_data_out<=123; end
//`endif
    default: begin
      debug_data_out<=0;
    end
  endcase
end


  
  reg [2:0] debug_spirom_send4_index;
  reg [1:0] debug_memcpy_step;
  reg [2:0] debug_readmem_step;
  reg [2:0] video_step;




  reg vga_debugger_read_line_ack_buff;
  reg transfer_highAddr;
  reg [23:0] command_timer;
  reg spirom_debug_read_ack_buff;
  reg spirom_debug_write_ack_buff;
  reg mem_read_ack_buff;
  reg mem_write_ack_buff;
  reg ins_read_ack_buff;
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      
      
      debug_readmem_step <= 0;
      debug_memcpy_step <= 0;
      transfer_regWriteEna_reg <= 0;
      transfer_highAddr <= 0;
      debug_flg <= 0;

      halt_debug<=1;
      debug_step<=0;
      debug_reset_n<=1;

      debug_address<=0;
      debug_writedata<=0;
      


      command_ack <= 0;
      debug_data_send<=0;
      //debug_data_out<=0;
      
      spirom_debug_read_req<=0;
      spirom_debug_write_req<=0;
      spirom_debug_write_data<=0;
      spirom_debug_cs <= 0;
      spirom_debug_read_ack_buff <= 0;
      spirom_debug_write_ack_buff <= 0;
      
      debug_spirom_send4_index <= 0;
      
      vga_control_by_debugger <= 0;
      vga_debugger_read_line_req <= 0;
      vga_debugger_read_line_part <= 0;
      vga_debugger_read_line_ack_buff <= 0;

      mem_read_req <= 0;
      mem_read_ack_buff <= 0;
      mem_write_req <= 0;
      mem_write_ack_buff <= 0;
      ins_read_req <= 0;
      ins_read_ack_buff <= 0;

      debug_hid <= 0;
      debug_hid_req <= 0;

      command_timer <= 0;
      debug_rw_cmd <= 0;//ldw
      fast <= 0;
      
      cpu_clk_sel <= 0;

    end else begin
      spirom_debug_read_ack_buff <=  spirom_debug_read_ack;
      spirom_debug_write_ack_buff <= spirom_debug_write_ack;
      vga_debugger_read_line_ack_buff <= vga_debugger_read_line_ack;
      mem_read_ack_buff <= mem_read_ack;
      mem_write_ack_buff <= mem_write_ack;
      ins_read_ack_buff <= ins_read_ack;
      
      debug_data_send <= 0;

      if(command_req && !command_ack)begin
        case(command[5:0])
        8'h00 : begin command_ack<=1; end

        //transfer_highAddr <= data[31]; 
        8'h01 : begin debug_data_send<=1; fast <= data[31]; vga_debugger_read_line_addr <= data[15:0]; command_ack<=1; end//VGA_DEBUGGER_READ_LINE_ADDR
        8'h02 : begin//VGA_DEBUGGER_READ_LINE_REQ
          case(video_step)
            0:begin
              video_step <= 1;
              vga_debugger_read_line_part<= 2'b00;
              vga_debugger_read_line_req <= 1;
            end
            1:begin
              if(vga_debugger_read_line_ack_buff)begin
                video_step <= 2;
                vga_debugger_read_line_part<= 2'b10;
                vga_debugger_read_line_req <= 0;
              end
            end
            2:begin
              if(!vga_debugger_read_line_ack_buff)begin
                video_step <= 3;
                vga_debugger_read_line_req <= 1;
              end
            end
            3:begin
              if(vga_debugger_read_line_ack_buff)begin
                //debug_data_out<=123;
                debug_data_send<=1;
                video_step <= 0;
                vga_debugger_read_line_addr <= vga_debugger_read_line_addr + 1'b1;
                vga_debugger_read_line_req <= 0;
                command_ack <= 1;
              end
            end
          endcase
        end
        
        8'h06 : begin debug_data_send<=1; vga_control_by_debugger <= data[0]; command_ack<=1; end//VGA_CONTROL_BY_DEBUGGER


        8'h07 : begin debug_data_send<=1; debug_commandFifo <= data[0]; command_ack<=1; end//VGA_CONTROL_BY_DEBUGGER
        8'h08 : begin debug_data_send<=1; debug_commandFifoAddr <= data; command_ack<=1; end//VGA_CONTROL_BY_DEBUGGER
        8'h09 : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h0A : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h0B : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h0C : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h0D : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO


        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        8'h10 : begin debug_data_send<=1; halt_debug<=data[0]; command_ack<=1; end //HALT_DEBUG
        8'h11 : begin debug_data_send<=1; cpu_clk_sel <= data[0]; command_ack<=1; end //SET_CPU_CLK
        8'h12 : begin debug_data_send<=1; debug_reset_n<=data[0]; command_ack<=1; end //DEBUG_RESET_N
        8'h14 : begin debug_data_send<=1; debug_step<=~debug_step; command_ack<=1; end //DEBUG_STEP
        8'h15 : begin debug_data_send<=1; debug_rw_cmd <= data[2:0]; command_ack<=1; end//SET_DEBUG_RW_CMD
        8'h16 : begin debug_data_send<=1; debug_address <= data; command_ack<=1; end//SET_DEBUG_ADDRESS
        8'h17 : begin debug_data_send<=1; debug_writedata <= data; command_ack<=1; end//SET_DEBUG_WRITEDATA
        8'h18 : begin debug_data_send<=1; debug_vga_base_addr<= data; command_ack<=1; end // SET_DEBUG_VGA_BASE_ADDR
        8'h19 : begin debug_data_send<=1; debug_flg <= data[0]; command_ack<=1; end //SET_DEBUG_FLG
        8'h1A : begin debug_data_send<=1; debug_hid <= data; command_ack<=1; end //SET_DEBUG_HID
        8'h1B : begin debug_data_send<=1; debug_hid_req <= data[0]; command_ack<=1; end //SET_DEBUG_HID_REQ

        8'h20 : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h21 : begin debug_data_send<=1; command_ack<=1; end //GET_PC_RECORD_DATA_EXT
        8'h22 : begin debug_data_send<=1; command_ack<=1; end //GET_ACCESS_TIME
        8'h23 : begin debug_data_send<=1; command_ack<=1; end //GET_AVM_M0_ADDRESS
        8'h24 : begin debug_data_send<=1; command_ack<=1; end //GET_CONST_ECHO
        8'h25 : begin debug_data_send<=1; command_ack<=1; end //GET_PC_RECORD_DATA
        8'h26 : begin debug_data_send<=1; command_ack<=1; end //GET_PC_RECORD_INDEX
        8'h27 : begin debug_data_send<=1; command_ack<=1; end //GET_MISC
        8'h28 : begin debug_data_send<=1; command_ack<=1; end //GET_IRQ_ID
        8'h29 : begin debug_data_send<=1; command_ack<=1; end //GET_CPU_ADDRESS
        8'h2A : begin debug_data_send<=1; command_ack<=1; end // GET_PC
        8'h2B : begin debug_data_send<=1; command_ack<=1; end // GET_MEM_SIZE
        8'h2C : begin debug_data_send<=1; command_ack<=1; end // GET_VGA_BASE_ADDR
        8'h2E : begin debug_data_send<=1; command_ack<=1; end //  GET_DEBUG_STASH_DATA
        8'h2F : begin debug_data_send<=1; command_ack<=1; end // GET_DEBUG_STASH_INDEX

  
        //mem read
        8'h30 : begin//MEM_READ
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            mem_read_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(mem_read_ack_buff)begin
              //debug_data_out <= avm_m0_readdata_latch;
              mem_read_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end

        //mem_write
        8'h31 : begin//MEM_WRITE
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            mem_write_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(mem_write_ack_buff)begin
              //debug_data_out<=123;
              mem_write_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end
        
        //ins read
        8'h32 : begin//INS_READ
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            ins_read_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(ins_read_ack_buff)begin
              //debug_data_out <= avm_m1_readdata_latch;
              ins_read_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end

        //内存批量 len = data, start = debug_address
        8'h34 : begin//MEM_TRANS_READ
          case(debug_memcpy_step)
          0:begin
            debug_address<=data;
            debug_memcpy_step <= 3;
          end
          1:begin
            if(mem_read_ack_buff)begin
              mem_read_req <= 0;
              transfer_regWriteEna_reg <= 1;
              debug_writedata <= avm_m0_readdata_latch;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!mem_read_ack_buff)begin
              transfer_regWriteEna_reg <= 0;
              debug_memcpy_step <= 3;
              debug_address[31:2] <= debug_address[31:2] + 1'b1;
            end
          end
          3:begin
            if(debug_address==data+1024)begin
              //debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
              debug_memcpy_step <= 0;
            end else begin
              debug_memcpy_step <= 1;
              mem_read_req <= 1;
            end
          end
          endcase
        end

        8'h35 : begin //MEM_TRANS_WRITE
          case(debug_memcpy_step)
          0:begin
            debug_address<=data;
            debug_memcpy_step <= 2;
          end
          1:begin
            if(mem_write_ack_buff)begin
              mem_write_req <= 0;
              debug_address[31:2] <= debug_address[31:2] + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!mem_write_ack_buff)begin
              debug_memcpy_step <= 3;
            end
          end
          3:begin
            if(debug_address==data+1024)begin
              //debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
              debug_memcpy_step <= 0;
            end else begin
              debug_writedata <= transfer_Data;
              debug_memcpy_step <= 1;
              mem_write_req <= 1;
            end
          end
          endcase
        end

        //reg read
        8'h37 : begin//REG_READ
          //assign debug_regAddr = debug_address[8:0]; //assign debug_regWriteData = debug_writedata;
          debug_data_send<=1;
          //debug_data_out <= debug_regData;
          command_ack <= 1;
        end
        
        //trans read
        8'h38 : begin//TRANS_READ
          //assign debug_regAddr = debug_address[8:0]; //assign debug_regWriteData = debug_writedata;
          debug_data_send<=1;
          //debug_data_out <= transfer_Data;
          command_ack <= 1;
        end
        
        //trans write
        8'h39 : begin//TRANS_WRITE
          //assign debug_regAddr = debug_address[8:0]; //assign debug_regWriteData = debug_writedata;
          if(debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            transfer_regWriteEna_reg <= 1;
          end else begin
            debug_data_send<=1;
            //debug_data_out<=123;
            debug_readmem_step <= 0;
            transfer_regWriteEna_reg <= 0;
            command_ack <= 1;
          end
        end

        // 8'h40 : begin//DEBUG_TX_TO_PC
        //   debug_tx_to_pc_read <= 1;
        //   debug_data_send<=1;
        //   debug_data_out<=debug_tx_to_pc;
        //   command_ack<=1;
        // end
        // 8'h41 : begin//DEBUG_TX_STATUS_TO_PC
        //   debug_data_send<=1;
        //   debug_data_out<=debug_tx_to_pc_valid;
        //   command_ack<=1;
        // end
        // 8'h42 : begin//DEBUG_RX_FROM_PC
        //   if(debug_rx_from_pc_valid)begin
        //     debug_data_send<=1;
        //     debug_data_out<=0;
        //   end else begin
        //     debug_data_send<=1;
        //     debug_data_out<=1;
        //     debug_rx_from_pc <= data;
        //     debug_rx_from_pc_valid <= 1;
        //   end
        //   command_ack<=1;
        // end

  

`ifdef NEEDSPI
        8'h70 : begin debug_data_send<=1; spirom_debug_cs <= 1'b0; command_ack<=1; end //SPIROM_DEBUG_CS0
        8'h71 : begin debug_data_send<=1; spirom_debug_cs <= 1'b1; command_ack<=1; end //SPIROM_DEBUG_CS1
        8'h72 : begin //SPIROM_REC
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            spirom_debug_read_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(spirom_debug_read_ack_buff)begin
              spirom_debug_read_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1; 
              //debug_data_out<=spirom_debug_read_data; 
              command_ack <= 1;
            end
          end
        end
        8'h73 : begin //SPIROM_SND
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            spirom_debug_write_data <= data[7:0];
            spirom_debug_write_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1; 
              //debug_data_out<=123; 
              command_ack <= 1;
            end
          end
        end
        8'h74 : begin //SPIROM_SND4
          case(debug_memcpy_step)
          0:begin
            //debug_address is zero
            case(debug_spirom_send4_index[1:0])
            0:spirom_debug_write_data <= data[7:0];
            1:spirom_debug_write_data <= data[15:8];
            2:spirom_debug_write_data <= data[23:16];
            3:spirom_debug_write_data <= data[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_memcpy_step <= 1;
          end
          1:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_spirom_send4_index <= debug_spirom_send4_index + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_memcpy_step <= 3;
            end
          end
          3:begin
            if(debug_spirom_send4_index==4)begin
              debug_spirom_send4_index <= 0;
              //debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
            end
            debug_memcpy_step <= 0;
          end
          endcase
        end
        
        //spirom 批量
                //内存批量 len = data start = debug_address
        8'h76 : begin //SPIROM_TRANS_WRITE
          case(debug_memcpy_step)
          0:begin
            //debug_address is zero
            case(debug_address[1:0])
            0:spirom_debug_write_data <= transfer_Data[7:0];
            1:spirom_debug_write_data <= transfer_Data[15:8];
            2:spirom_debug_write_data <= transfer_Data[23:16];
            3:spirom_debug_write_data <= transfer_Data[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_memcpy_step <= 1;
          end
          1:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_address <= debug_address + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_memcpy_step <= 3;
            end
          end
          3:begin
            if(debug_address==data)begin
              //debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
            end
            debug_memcpy_step <= 0;
          end
          endcase
        end
`endif

        default: begin
          command_ack<=1;
        end

        
        endcase

        if(command_timer[23])begin
          command_timer <= 0;
          //debug_read <= 0;
          //debug_write <= 0;
          //debug_read_ins <= 0;
          debug_memcpy_step <= 0;
          debug_readmem_step <= 0;
          transfer_regWriteEna_reg <= 0;
          spirom_debug_read_req <= 0;
          spirom_debug_write_req <= 0;
          debug_data_send<=1; command_ack <= 1;
        end
      end

      if(!command_req && command_ack)begin
        command_ack<=0;
      end
      
      if(!debug_tx_to_pc_valid && debug_tx_to_pc_read)begin
        debug_tx_to_pc_read <= 0;
      end
      
      if(debug_rx_from_pc_read && debug_rx_from_pc_valid)begin
        debug_rx_from_pc_valid <= 0;
      end

    end
  end

endmodule



(* bram_map="yes" *)
module transferBuff (
input clk,
input [8-1:0] addr_r,
input [8-1:0] addr_w,
input [32-1:0] in,
input we,
output [31:0] out
);

  //(* ram_style = "distributed" *) reg [31:0] mem[255:0];
  (* ram_style = "block" *) reg [32-1:0] mem[2**8-1:0];
  
  reg [8-1:0] _addr;
  always @(posedge clk)
  begin
      _addr <= addr_r;
  end

  assign out = mem[_addr];
  
  always @(posedge clk)
  begin
      if (we) begin
          mem[addr_w] <= in;
      end
  end
endmodule 

